package pac1_rgr;

import process.Dispatcher;
import queues.QueueForTransactions;
import queues.Store;
import qusystem.MultiActor;
import stat.DiscretHisto;
import stat.Histo;
import transProcess.ITransProcesable;
import widgets.experiments.IExperimentable;

public class Model implements IExperimentable, ITransProcesable{
	private Main gui;
	private Dispatcher dispatcher;
	private Barge barge;
	private Workers workers;
	private QueueForTransactions queueOfBarges;
	private QueueForTransactions queueOfCars;
	private QueueForTransactions queueOfWorkers;
	private QueueForTransactions queuePort;
	private QueueForTransactions queuePlatform;
	private GenerBarge generBarge;
	private MultiActor multiCar;
	private MultiActor multiWorker;
	private DiscretHisto discretHisto;
	private Histo histo;
	private double sum;
	private double lastSumTime=0;
	private double accumTime;
	
	public Model(Dispatcher d, Main g) {
		if (d == null || g == null) {
			System.out.println("Не визначено диспетчера або GUI для Model");
			System.out.println("Подальша робота неможлива");
			System.exit(0);
		}
		dispatcher = d;
		gui = g;
		// Передаємо акторів до стартового списку диспетчера
		componentsToStartList();

	}
    public Dispatcher getDispatcher (){
    	return this.dispatcher;
    }
	public void componentsToStartList() {
		// Передаємо акторів диспетчеру
		dispatcher.addStartingActor(getGenerBarge());
		dispatcher.addStartingActor(getMultiCar());
		dispatcher.addStartingActor(getMultiWorker());
		dispatcher.addStartingActor(new Time(gui));
	}

	private GenerBarge getGenerBarge() {

		if (generBarge == null) {
			generBarge = new GenerBarge("Генератор барж", gui, this);
		}
		return generBarge;
	}

	public Workers getWorkers() {
		if (workers == null) {
			workers = new Workers("Бригади ", gui, this);
		}
		return workers;
	}

	public QueueForTransactions getQueueOfBarges() {
		if (queueOfBarges == null) {
			queueOfBarges = new QueueForTransactions();
			queueOfBarges.setNameForProtocol("Черга барж");
			queueOfBarges.setDispatcher(dispatcher);
		}
		return queueOfBarges;
	}

	public QueueForTransactions getQueueOfCars() {
		if (queueOfCars == null) {
			queueOfCars = new QueueForTransactions();
			queueOfCars.setNameForProtocol("Черга автомобiлiв");
			queueOfCars.setDispatcher(dispatcher);
		}
		return queueOfCars;
	}

	public QueueForTransactions getQueueOfWorkers() {
		if (queueOfWorkers == null) {
			queueOfWorkers = new QueueForTransactions();
			queueOfWorkers.setNameForProtocol("Черга бригад");
			queueOfWorkers.setDispatcher(dispatcher);
		}
		return queueOfWorkers;
	}
	
	public QueueForTransactions getQueuePort() {
		if (queuePort == null) {
			queuePort = new QueueForTransactions();
			queuePort.setNameForProtocol("Черга контейнерiв у порту");
			queuePort.setDispatcher(dispatcher);
		}
		return queuePort;
	}

	public QueueForTransactions getQueuePlatform() {
		if (queuePlatform == null) {
			queuePlatform = new QueueForTransactions();
			queuePlatform.setNameForProtocol("Черга платформи");
			queuePlatform.setDispatcher(dispatcher);
		}
		return queuePlatform;
	}

	public void initForTest() {
		getQueueOfCars().setPainter(gui.getDiagramQueueCars().getPainter());
		getQueuePlatform()
				.setPainter(gui.getDiagramContPlatform().getPainter());
		getQueuePort().setPainter(gui.getDiagramContPort().getPainter());
		getQueueOfWorkers().setPainter(
				gui.getDiagramQueueWorkers().getPainter());
	}

	public void initForStat() {
		//getQueuePlatform().setPainter(gui.getDiagramStat().getPainter());
		gui.getDiscretHisto().init();
		dispatcher.setProtocolFileName("");
	}
	public MultiActor getMultiCar() {
		if (multiCar == null) {
			multiCar = new MultiActor();
			multiCar.setNumberOfClones(gui.getChooseDataCars().getInt());
			multiCar.setOriginal(new Car("Автомобiль ", this.gui, this));
		}
		return multiCar;
	}

	public MultiActor getMultiWorker() {
		if (multiWorker == null) {
			multiWorker = new MultiActor();
			multiWorker.setNumberOfClones(gui.getChooseDataWorkers().getInt());
			multiWorker.setOriginal(new Workers("Бригада ", this.gui, this));
		}
		return multiWorker;
	}
	public void initForExperiment(double finishTime, double factor) {

		getMultiCar().setNumberOfClones((int) factor);
		//getDispatcher().setProtocolFileName("");
		getQueuePort().init();
		getQueueOfCars().init();
		getQueueOfCars().setPainter(null);
		getQueuePort().setPainter(null);
		gui.getChooseDataModelTime().setText(String.valueOf(finishTime));
		gui.getChooseDataCars().setText(String.valueOf(factor));
		if (gui.getJRadioButton().isSelected()){
			getQueuePort().setDiscretHisto(getDiscretHisto());
			getHisto().init();
		}
		else gui.getHisto1().init();
	}
	public DiscretHisto getDiscretHisto() {
		if (discretHisto == null) {
			discretHisto = new DiscretHisto();
		}
		return discretHisto;
	}
	
	public Histo getHisto() {
		if (histo == null) {
			histo = new Histo();
		}
		return histo;
	}
	
	@Override
	public double getResultOfExperiment() {
		if (gui.getJRadioButton().isSelected()){
			return getDiscretHisto().getAverage();
		}
		else return gui.getHisto1().getAverage();
	}
	@Override
	public double getTransResult() {
		// TODO Auto-generated method stub
		double dt = getDispatcher().getCurrentTime() - lastSumTime;
		lastSumTime = getDispatcher().getCurrentTime();
		sum += dt * getQueueOfCars().size();
		accumTime += dt;
		return sum / accumTime;
		
	}
	@Override
	public void initForTrans(double d) {
		// TODO Auto-generated method stub
		getGui().getChooseDataModelTime().setText(String.valueOf(d));
		int modelID = hashCode();
		getQueueOfCars().init();
		getQueueOfCars().setNameForProtocol("Черга автомобілів" + modelID);	
		getQueueOfCars().setPainter(null);
		getMultiCar().setNumberOfClones(gui.getChooseDataCars().getInt());
	}
	private Main getGui() {
		// TODO Auto-generated method stub
		if(gui==null)System.out.println("Не визначено GUI для моделі");
		return gui;
	}
	@Override
	public void resetTransAccum() {
		// TODO Auto-generated method stub
		lastSumTime = getDispatcher().getCurrentTime();
		sum = 0;
		accumTime = 0;
	}
}
